/*
 * FaceCat图形通讯框架
 * 著作权编号:2015SR229355+2020SR0266727
 * 上海卷卷猫信息技术有限公司
 */

using System;
using System.Collections.Generic;
using System.Text;

namespace FaceCat {
    /// <summary>
    /// 数值显示视图
    /// </summary>
    public class FCSpin : FCTextBox {
        /// <summary>
        /// 创建数值显示视图
        /// </summary>
        public FCSpin() {
            setTextAlign(FCHorizontalAlign.Center);
        }

        /// <summary>
        /// TICK值
        /// </summary>
        private int m_tick = 0;

        /// <summary>
        /// 秒表ID
        /// </summary>
        private int m_timerID = getNewTimerID();

        public bool m_autoFormat = true;

        /// <summary>
        /// 获取是否自动格式化
        /// </summary>
        public virtual bool autoFormat() {
            return m_autoFormat;
        }

        /// <summary>
        /// 设置是否自动格式化
        /// </summary>
        public virtual void setAutoFormat(bool value) {
            m_autoFormat = value;
        }

        public bool m_autoFormatInput;

        /// <summary>
        /// 是否在输入时自动格式化
        /// </summary>
        /// <returns></returns>
        public virtual bool autoFormatInput()
        {
            return m_autoFormatInput;
        }

        /// <summary>
        /// 设置是否在输入时自动格式化
        /// </summary>
        /// <param name="value"></param>
        public virtual void setAutoFormatInput(bool value)
        {
            m_autoFormatInput = value;
        }

        public int m_digit = 0;

        /// <summary>
        /// 获取保留小数的位数
        /// </summary>
        public virtual int getDigit() {
            return m_digit;
        }

        /// <summary>
        /// 设置保留小数的位数
        /// </summary>
        public virtual void setDigit(int value) {
            m_digit = value;
            if (m_autoFormat) {
                if (m_text.Equals("")) {
                    m_text = "0";
                }
                setText(getValueByDigit(getValue(), m_digit));
            }
        }

        public FCButton m_downButton;

        /// <summary>
        /// 获取向下按钮
        /// </summary>
        public virtual FCButton getDownButton() {
            return m_downButton;
        }

        /// <summary>
        /// 设置向下按钮
        /// </summary>
        public virtual void setDownButton(FCButton value) {
            m_downButton = value;
        }

        public bool m_isAdding;

        /// <summary>
        /// 获取是否正在增量
        /// </summary>
        public virtual bool isAdding() {
            return m_isAdding;
        }

        /// <summary>
        /// 设置是否正在增量
        /// </summary>
        public virtual void setIsAdding(bool value) {
            if (m_isAdding != value) {
                m_isAdding = value;
                m_tick = 0;
                if (m_isAdding) {
                    startTimer(m_timerID, 10);
                } else {
                    stopTimer(m_timerID);
                }
            }
        }

        public bool m_isReducing;

        /// <summary>
        /// 获取是否正在减量
        /// </summary>
        public virtual bool isReducing() {
            return m_isReducing;
        }

        /// <summary>
        /// 设置是否正在减量
        /// </summary>
        public virtual void setIsReducing(bool value) {
            if (m_isReducing != value) {
                m_isReducing = value;
                m_tick = 0;
                if (m_isReducing) {
                    startTimer(m_timerID, 10);
                } else {
                    stopTimer(m_timerID);
                }
            }
        }

        public double m_maximum = 100;

        /// <summary>
        /// 获取最大值
        /// </summary>
        public virtual double getMaximum() {
            return m_maximum;
        }

        /// <summary>
        /// 设置最大值
        /// </summary>
        public virtual void setMaximum(double value) {
            m_maximum = value;
            if (getValue() > value) {
                setValue(value);
            }
        }

        public double m_minimum = 0;

        /// <summary>
        /// 获取最小值
        /// </summary>
        public virtual double getMinimum() {
            return m_minimum;
        }

        /// <summary>
        /// 设置最小值
        /// </summary>
        public virtual void setMinimum(double value) {
            m_minimum = value;
            if (getValue() < value) {
                setValue(value);
            }
        }

        public bool m_showThousands;

        /// <summary>
        /// 获取是否显示千分位
        /// </summary>
        public virtual bool showThousands() {
            return m_showThousands;
        }

        /// <summary>
        /// 设置是否显示千分位
        /// </summary>
        public virtual void setShowThousands(bool value) {
            m_showThousands = value;
        }

        public double m_step = 1;

        /// <summary>
        /// 获取数值增减幅度
        /// </summary>
        public virtual double getStep() {
            return m_step;
        }

        /// <summary>
        /// 设置数值增减幅度
        /// </summary>
        public virtual void setStep(double value) {
            m_step = value;
        }

        /// <summary>
        /// 获取文本
        /// </summary>
        public override void setText(String value) {
            base.setText(formatNum(value.Replace(",", "")));
        }

        public FCButton m_upButton;

        /// <summary>
        /// 获取向上按钮
        /// </summary>
        public virtual FCButton getUpButton() {
            return m_upButton;
        }

        /// <summary>
        /// 设置向上按钮
        /// </summary>
        public virtual void setUpButton(FCButton value) {
            m_upButton = value;
        }

        /// <summary>
        /// 获取数值
        /// </summary>
        public virtual double getValue() {
            return FCTran.strToDouble(getText().Replace(",", ""));
        }

        /// <summary>
        /// 设置数值
        /// </summary>
        public virtual void setValue(double value) {
            if (value > m_maximum) {
                value = m_maximum;
            }
            if (value < m_minimum) {
                value = m_minimum;
            }
            double oldValue = getValue();
            setText(formatNum(getValueByDigit(value, m_digit)));
            onValueChanged();
        }

        /// <summary>
        /// 增加指定幅度的数值
        /// </summary>
        public virtual void add() {
            setValue(getValue() + m_step);
        }

        /// <summary>
        /// 触摸事件回调
        /// </summary>
        /// <param name="eventName"></param>
        /// <param name="sender"></param>
        /// <param name="touchInfo"></param>
        /// <param name="invoke"></param>
        public override void callTouchEvent(String eventName, Object sender, FCTouchInfo touchInfo, Object invoke) {
            base.callTouchEvent(eventName, sender, touchInfo, invoke);
            if (eventName == "ontouchdown") {
                if (sender == m_downButton) {
                    reduce();
                    setIsReducing(true);
                    invalidate();
                } else if (sender == m_upButton) {
                    add();
                    setIsAdding(true);
                    invalidate();
                }
            } else if (eventName == "ontouchup") {
                if (sender == m_downButton) {
                    setIsReducing(false);
                } else if (sender == m_upButton) {
                    setIsAdding(false);
                }
            }
        }

        /// <summary>
        /// 销毁方法
        /// </summary>
        public override void delete() {
            if (!isDeleted()) {
                if (m_downButton != null) {
                    m_downButton.removeEvent(this, "ontouchdown");
                    m_downButton.removeEvent(this, "ontouchup");
                }
                if (m_upButton != null) {
                    m_upButton.removeEvent(this, "ontouchdown");
                    m_upButton.removeEvent(this, "ontouchup");
                }
            }
            base.delete();
        }

        /// <summary>
        /// 将文本转化为千分位显示
        /// </summary>
        /// <param name="inputText">输入文字</param>
        /// <returns>千分位文字</returns>
        public virtual String formatNum(String inputText) {
            if (m_showThousands) {
                inputText = inputText.Replace(",", "");
                String theNewText = "";
                int pos = 0;
                bool hasMinusSign = false;
                if (inputText.IndexOf("-") == 0) {
                    hasMinusSign = true;
                    inputText = inputText.Substring(1);
                }
                String textAfterDot = String.Empty;
                bool hasDot = false;
                if (inputText.Contains(".")) {
                    hasDot = true;
                    textAfterDot = inputText.Substring(inputText.IndexOf(".") + 1);
                    inputText = inputText.Remove(inputText.IndexOf("."));
                }
                pos = inputText.Length;
                while (pos >= 0) {
                    int logicPos = inputText.Length - pos;
                    if ((logicPos % 3) == 0 && logicPos > 1) {
                        if (theNewText == "") {
                            theNewText = inputText.Substring(pos, 3);
                        } else {
                            theNewText = inputText.Substring(pos, 3) + "," + theNewText;
                        }
                    } else {
                        if (pos == 0) {
                            if (theNewText == "") {
                                theNewText = inputText.Substring(pos, (logicPos % 3));
                            } else {
                                theNewText = inputText.Substring(pos, (logicPos % 3)) + "," + theNewText;
                            }

                        }
                    }
                    --pos;
                }
                if (hasMinusSign) {
                    theNewText = "-" + theNewText;
                }
                if (hasDot) {
                    theNewText = theNewText + "." + textAfterDot;
                }
                if (theNewText.IndexOf(".") == 0) {
                    theNewText = "0" + theNewText;
                }
                if (theNewText.IndexOf("-.") == 0) {
                    theNewText = theNewText.Insert(1, "0");
                }
                return theNewText;
            } else {
                return inputText;
            }
        }

        /// <summary>
        /// 获取视图类型
        /// </summary>
        /// <returns>视图类型</returns>
        public override String getViewType() {
            return "Spin";
        }

        /// <summary>
        /// 获取事件名称列表
        /// </summary>
        /// <returns>名称列表</returns>
        public override ArrayList<String> getEventNames() {
            ArrayList<String> eventNames = base.getEventNames();
            eventNames.AddRange(new String[] { "ValueChanged" });
            return eventNames;
        }

        /// <summary>
        /// 获取属性值
        /// </summary>
        /// <param name="name">属性名称</param>
        /// <param name="value">返回属性值</param>
        /// <param name="type">返回属性类型</param>
        public override void getAttribute(String name, ref String value, ref String type) {
            switch (name)
            {
                case "autoformat":
                    type = "bool";
                    value = FCTran.boolToStr(autoFormat());
                    break;
                case "autoformatinput":
                    type = "bool";
                    value = FCTran.boolToStr(autoFormatInput());
                    break;
                case "digit":
                    type = "int";
                    value = FCTran.doubleToStr(getDigit());
                    break;
                case "maximum":
                    type = "double";
                    value = FCTran.doubleToStr(getMaximum());
                    break;
                case "minimum":
                    type = "double";
                    value = FCTran.doubleToStr(getMinimum());
                    break;
                case "showthousands":
                    type = "bool";
                    value = FCTran.boolToStr(showThousands());
                    break;
                case "step":
                    type = "double";
                    value = FCTran.doubleToStr(getStep());
                    break;
                case "value":
                    type = "double";
                    value = FCTran.doubleToStr(getValue());
                    break;
                default:
                    base.getAttribute(name, ref value, ref type);
                    break;
            }
        }

        /// <summary>
        /// 获取属性名称列表
        /// </summary>
        /// <returns>属性名称列表</returns>
        public override ArrayList<String> getAttributeNames() {
            ArrayList<String> attributeNames = base.getAttributeNames();
            attributeNames.AddRange(new String[] { "AutoFormat", "AutoFormatInput", "Digit", "Maximum", "Minimum", "ShowThousands", "Step" });
            return attributeNames;
        }

        /// <summary>
        /// 根据保留小数的位置将double型转化为String型
        /// </summary>
        /// <param name="value">值</param>
        /// <param name="digit">保留小数点</param>
        /// <returns>数值字符</returns>
        public String getValueByDigit(double value, int digit) {
            if (digit > 0) {
                StringBuilder format = new StringBuilder();
                format.Append("0");
                format.Append(".");
                for (int i = 0; i < digit; i++) {
                    format.Append("0");
                }
                return value.ToString(format.ToString());
            } else {
                return value.ToString("0");
            }
        }

        /// <summary>
        /// 输入文字方法
        /// </summary>
        /// <param name="ch">字符</param>
        public override void onChar(char ch) {
            if (m_autoFormat && m_autoFormatInput) {
                callEvents("onchar");
                FCHost host = getNative().getHost();
                if (!host.isKeyPress(0x11)) {
                    bool flag = false;
                    if (getSelectionLength() > 0) {
                        flag = true;
                    }
                    char inputCharacter = ch;
                    int curPos = getSelectionStart();
                    bool cursorIsLast = false;
                    if (curPos == m_text.Length) {
                        cursorIsLast = true;
                    }
                    int exCount = 0;
                    if (inputCharacter == 8) {
                        if (getSelectionLength() > 0) {
                            if (getSelectionStart() > 0 && m_text[getSelectionStart() - 1] == ',') {
                                setSelectionStart(getSelectionStart() - 1);
                                setSelectionLength(getSelectionLength() + 1);
                                curPos = getSelectionStart();
                            }
                            setText(formatNum(getText()));
                            setSelectionStart(curPos);
                        } else {
                            if (getSelectionStart() > 0 && m_text[getSelectionStart() - 1] == ',') {
                                setSelectionStart(getSelectionStart() - 1);
                                curPos = getSelectionStart();
                            }

                            if (getSelectionStart() > 0 && m_text[getSelectionStart() - 1] == '.') {
                                String sub = m_text.Substring(getSelectionStart());
                                exCount = sub.Length / 3;
                            }
                            int length = m_text.Length - curPos;
                            String oriText = getText();
                            int diff = 0;
                            if (oriText.StartsWith(",")) {
                                oriText = oriText.Substring(1);
                                diff = 1;
                            }
                            m_text = formatNum(getText());
                            if (getText().Length + diff - exCount - length > 0) {
                                setSelectionStart(m_text.Length + diff - exCount - length);
                            }
                        }
                        invalidate();
                        return;
                    }
                    if (inputCharacter == 46) {
                        if (m_text.Contains(".")) {
                            if (m_text.IndexOf(".") != m_text.Length - 1) {
                                setSelectionStart(m_text.IndexOf(".") + 1);
                            }
                            invalidate();
                            return;
                        }
                    }
                    int backLength = m_text.Length - curPos;
                    if (inputCharacter == 46) {
                        String sub = m_text.Substring(getSelectionStart());
                        exCount = sub.Length - sub.Replace(",", "").Length;
                        insertWord(ch.ToString());
                        onTextChanged();
                        onValueChanged();
                        invalidate();
                        return;
                    }
                    bool removeCharFlag = false;
                    if (m_selectionLength > 0 && m_selectionLength == m_text.Length) {
                        m_text = "";
                        setSelectionLength(0);
                    } else if (m_text.StartsWith("0.")) {
                        if (getSelectionStart() == 0) {
                            removeCharFlag = true;
                            m_text = m_text.Substring(1);
                            setSelectionLength(0);
                        }
                    }
                    String oldText = getText();
                    int index = m_text.IndexOf(".");
                    if (m_selectionLength == 0 && index < getSelectionStart()) {
                        m_selectionLength = 1;
                    }
                    insertWord(ch.ToString());
                    int selectionStart = getSelectionStart();
                    setRegion();
                    m_selectionLength = 0;
                    String newText = getText();
                    if (newText.Length > 0 && selectionStart > newText.Length) {
                        setSelectionStart(newText.Length);
                    }
                    if (((m_text.IndexOf(".") != -1) && (m_text.IndexOf(".") < selectionStart)) || flag) {
                        setSelectionStart(selectionStart);
                    } else {
                        if (cursorIsLast == true) {
                            setSelectionStart(m_text.Length + 1);
                        } else {
                            if (m_text.Length + exCount - backLength >= 0) {
                                setSelectionStart(m_text.Length + exCount - backLength);
                            }
                        }
                    }
                    if (removeCharFlag) {
                        setSelectionStart(getSelectionStart() + 1);
                    }
                    m_showCursor = true;
                    onTextChanged();
                    onValueChanged();
                    invalidate();
                }
            } else {
                base.onChar(ch);
            }
        }

        /// <summary>
        /// 键盘按下方法
        /// </summary>
        /// <param name="key">按键</param>
        public override void onKeyDown(char key) {
            if (m_autoFormat && m_autoFormatInput) {
                if (key == 8 || key == 46) {
                    String text = getText();
                    if (text.Length > 0) {
                        int curPos = getSelectionStart();
                        if (text.IndexOf(".") != -1 && text.IndexOf(".") == curPos - 1 && getSelectionLength() <= 1) {
                            setSelectionStart(curPos - 1);
                            curPos = getSelectionStart();
                        }
                        if (getSelectionStart() == 0) {
                            int len = getSelectionLength() + 1;
                            if (len > text.Length) {
                                len = text.Length;
                            }
                            m_text = text.Substring(len);
                        } else {
                            deleteWord();
                        }
                        bool deleteAll = m_text.Length == 0;
                        setRegion();
                        if (curPos > 0) {
                            setSelectionStart(curPos - 1);
                        } else {
                            setSelectionStart(curPos);
                        }
                        if (deleteAll) {
                            setSelectionStart(m_text.Length);
                            setSelectionLength(0);
                        } else if (curPos == 0 && m_text.IndexOf("0.") == 0) {
                            setSelectionStart(m_text.Length);
                        }
                        m_showCursor = true;
                        onTextChanged();
                        onValueChanged();
                        invalidate();
                        return;
                    }
                }
            }
            base.onKeyDown(key);
            FCHost host = getNative().getHost();
            if (!host.isKeyPress(0x10) && !host.isKeyPress(0x11) && !host.isKeyPress(0x12)) {
                if (key == 38) {
                    add();
                    invalidate();
                } else if (key == 40) {
                    reduce();
                    invalidate();
                }
            }
        }

        /// <summary>
        /// 添加视图方法
        /// </summary>
        public override void onLoad() {
            base.onLoad();
            FCHost host = getNative().getHost();
            if (m_downButton == null) {
                m_downButton = host.createInternalView(this, "downbutton") as FCButton;
                m_downButton.addEvent(this, "ontouchdown", null);
                m_downButton.addEvent(this, "ontouchup", null);
                addView(m_downButton);
            }
            if (m_upButton == null) {
                m_upButton = host.createInternalView(this, "upbutton") as FCButton;
                m_upButton.addEvent(this, "ontouchdown", null);
                m_upButton.addEvent(this, "ontouchup", null);
                addView(m_upButton);
            }
            update();
        }

        /// <summary>
        /// 触摸滚动方法
        /// </summary>
        /// <param name="touchInfo">触摸信息</param>
        public override void onTouchWheel(FCTouchInfo touchInfo) {
            base.onTouchWheel(touchInfo);
            if (touchInfo.m_delta > 0) {
                add();
            } else if(touchInfo.m_delta < 0){
                reduce();
            }
            invalidate();
        }

        /// <summary>
        /// 粘贴方法
        /// </summary>
        public override void onPaste() {
            if (m_autoFormat && m_autoFormatInput) {
                callEvents("onpaste");
                FCHost host = getNative().getHost();
                String insert = host.paste();
                if (insert != null && insert.Length > 0) {
                    insertWord(insert);
                    setText(formatNum(getValueByDigit(getValue(), m_digit)));
                    onTextChanged();
                    onValueChanged();
                    invalidate();
                }
            } else {
                base.onPaste();
            }
        }

        /// <summary>
        /// 丢失焦点方法
        /// </summary>
        public override void onLostFocus()
        {
            base.onLostFocus();
            if (m_autoFormat)
            {
                double value = FCTran.strToDouble(getText());
                if (value > m_maximum)
                {
                    value = m_maximum;
                }
                if (value < m_minimum)
                {
                    value = m_minimum;
                }
                double oldValue = getValue();
                String oldText = getText();
                setText(formatNum(getValueByDigit(value, m_digit)));
                if (oldText != getText())
                {
                    onTextChanged();
                }
                if (oldValue != getValue())
                {
                    onValueChanged();
                }
                invalidate();
            }
        }

        /// <summary>
        /// 秒表事件
        /// </summary>
        /// <param name="timerID">秒表ID</param>
        public override void onTimer(int timerID) {
            base.onTimer(timerID);
            if (timerID == m_timerID) {
                if (m_tick > 20) {
                    if (m_tick > 50 || m_tick % 3 == 1) {
                        if (m_isAdding) {
                            add();
                            invalidate();
                        } else if (m_isReducing) {
                            reduce();
                            invalidate();
                        }
                    }
                }
                m_tick++;
            }
        }

        /// <summary>
        /// 数值改变时触发
        /// </summary>
        public virtual void onValueChanged() {
            callEvents("onvaluechanged");
        }

        /// <summary>
        /// 减少指定幅度的数值
        /// </summary>
        public void reduce() {
            setValue(getValue() - m_step);
        }

        /// <summary>
        /// 设置属性
        /// </summary>
        /// <param name="name">属性名称</param>
        /// <param name="value">属性值</param>
        public override void setAttribute(String name, String value)
        {
            switch (name)
            {
                case "autoformat":
                    setAutoFormat(FCTran.strToBool(value));
                    break;
                case "autoformatinput":
                    setAutoFormatInput(FCTran.strToBool(value));
                    break;
                case "digit":
                    setDigit(FCTran.strToInt(value));
                    break;
                case "maximum":
                    setMaximum(FCTran.strToDouble(value));
                    break;
                case "minimum":
                    setMinimum(FCTran.strToDouble(value));
                    break;
                case "showthousands":
                    setShowThousands(FCTran.strToBool(value));
                    break;
                case "step":
                    setStep(FCTran.strToDouble(value));
                    break;
                case "value":
                    setValue(FCTran.strToDouble(value));
                    break;
                default:
                    base.setAttribute(name, value);
                    break;
            }
        }

        /// <summary>
        /// 设置区域
        /// </summary>
        public void setRegion() {
            String textValue = m_text.Replace(",", "");
            if (textValue == null || textValue == "") {
                textValue = "0";
            }
            if (textValue.IndexOf(".") != -1 && textValue.IndexOf(".") == 0) {
                textValue = "0" + textValue;
            }
            double value = FCTran.strToDouble(textValue);
            if (value > getMaximum()) {
                value = getMaximum();
            }
            if (value < getMinimum()) {
                value = getMinimum();
            }
            setText(formatNum(getValueByDigit(value, m_digit)));
        }

        /// <summary>
        /// 向上按钮的触摸按下事件
        /// </summary>
        /// <param name="sender">发送者</param>
        /// <param name="touchInfo">触摸信息</param>
        private void upButtonTouchDown(Object sender, FCTouchInfo touchInfo, Object invoke) {
            add();
            setIsAdding(true);
            invalidate();
        }

        /// <summary>
        /// 向上按钮的触摸抬起事件
        /// </summary>
        /// <param name="sender">发送者</param>
        /// <param name="touchInfo">触摸信息</param>
        private void upButtonTouchUp(Object sender, FCTouchInfo touchInfo, Object invoke) {
            setIsAdding(false);
        }

        /// <summary>
        /// 更新布局方法
        /// </summary>
        public override void update() {
            if (m_native != null && !m_native.m_lockUpdate)
            {
                base.update();
                int width = getWidth(), height = getHeight();
                if (m_upButton != null)
                {
                    int uWidth = getHeight();
                    FCPoint location = new FCPoint(width - uWidth, 0);
                    m_upButton.setLocation(location);
                    FCSize size = new FCSize(uWidth, height);
                    m_upButton.setSize(size);
                }
                if (m_downButton != null)
                {
                    int dWidth = getHeight();
                    FCPoint location = new FCPoint(0, 0);
                    m_downButton.setLocation(location);
                    FCSize size = new FCSize(dWidth, height);
                    m_downButton.setSize(size);
                }
            }
        }
    }
}
